﻿using System;
using UnityEngine;

public class RandomHelper
{
    /// <summary>
    /// 生成器刷新时间, 小于或等于0 时 永不刷新, 短跳方式实现常量编译
    /// </summary>
    private const float kRegenerateInterval = 0;
    /// <summary>
    /// 不允许直接通过该字段直接获取值
    /// </summary>
    private static System.Random randomisation;
    /// <summary>
    /// 记录最后生成器生成时间
    /// </summary>
    private static float lastGenerateTime;
    /// <summary>
    /// 随机生成器可能改变
    /// </summary>
    public static System.Random Randomisation
    {
        get
        {
            if ((randomisation == null) ||
                ((kRegenerateInterval > 0) && (Time.realtimeSinceStartup - lastGenerateTime > kRegenerateInterval)))
            {
                lastGenerateTime = Time.realtimeSinceStartup;
                randomisation = CreateRandom();
            }
            return randomisation;
        }
    }

    #region 随机
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static System.Random CreateRandom()
    {
        long tick = DateTime.Now.Ticks;

        int seed = 0;
        unchecked
        {
            seed = (int)(tick & 0xffffffffL) | (int)(tick >> 32);
        }

        return new System.Random(seed);
    }

    /// <summary>
    /// 在指定矩形空间随机获取一个坐标点
    /// </summary>
    /// <param name="min">需要保证每一个分量都小于max</param>
    /// <param name="max">需要保证每一个分量都大于min</param>
    /// <returns></returns>
    public static Vector3 RandomVector(Vector3 min, Vector3 max)
    {
        return RandomVector(max - min) + min;
    }

    /// <summary>
    /// 在指定矢量中随机获取一个坐标点
    /// </summary>
    /// <param name="dirVector3">需要保证每一个分量都不小于0</param>
    /// <returns></returns>
    private static Vector3 RandomVector(Vector3 dirVector3)
    {
        return new Vector3(Range(0, dirVector3.x), Range(0, dirVector3.y), Range(0, dirVector3.z));
    }

    /// <summary>
    /// 标量类型或者支持比较符的混淆范围的随机数
    /// 对于未区分值大小的随机取值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obscureBorder0">混淆边界</param>
    /// <param name="obscureBorder1">混淆边界</param>
    /// <returns></returns>
    public static int RandomRangeObscure(int obscureBorder0, int obscureBorder1)
    {
        if (obscureBorder0 == obscureBorder1)
        {
            return obscureBorder0;
        }

        if (obscureBorder0 < obscureBorder1)
        {
            return UnityEngine.Random.Range(obscureBorder0, obscureBorder1);
        }

        return UnityEngine.Random.Range(obscureBorder1, obscureBorder0);
    }
    /// <summary>
    /// 标量类型或者支持比较符的混淆范围的随机数
    /// 对于未区分值大小的随机取值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obscureBorder0">混淆边界</param>
    /// <param name="obscureBorder1">混淆边界</param>
    /// <returns></returns>
    public static float RandomRangeObscure(float obscureBorder0, float obscureBorder1)
    {
        if (obscureBorder0.Equals(obscureBorder1))
        {
            return obscureBorder0;
        }

        if (obscureBorder0 < obscureBorder1)
        {
            return UnityEngine.Random.Range(obscureBorder0, obscureBorder1);
        }

        return UnityEngine.Random.Range(obscureBorder1, obscureBorder0);
    }

    /// <summary>
    /// 获取随机色, 包括不透明度
    /// </summary>
    /// <returns></returns>
    public static Color RandomAlphaColor()
    {
        Byte[] temp = new Byte[4];
        Randomisation.NextBytes(temp);
        return new Color(temp[0], temp[1], temp[2], temp[3]);
    }

    /// <summary>
    /// 随机圆圈内平面位置(默认Y向上, 暂时不可选)
    /// </summary>
    /// <param name="center">中心</param>
    /// <param name="radius">半径</param>
    /// <returns></returns>
    public static Vector3 RandomPlanarPosition(Vector3 center, float radius)
    {
        if (radius <= 0)
        {
            return center;
        }
        return center + RandomPlanarDirection() * Range(0, radius);
    }

    /// <summary>
    /// 随机平面方向规范化向量
    /// </summary>
    /// <returns></returns>
    public static Vector3 RandomPlanarDirection()
    {
        return Quaternion.AngleAxis(Range(0, 360), Vector3.up) * Vector3.forward;
    }

    /// <summary>
    /// 获取随机色, Alpha 为 1
    /// </summary>
    /// <returns></returns>
    public static Color RandomColor()
    {
        Byte[] temp = new Byte[4];
        Randomisation.NextBytes(temp);
        return new Color(temp[0], temp[1], temp[2], 255);
    }

    /// <summary>
    /// 获取随机色, 用指定alpha值填充, 0~255
    /// </summary>
    /// <returns></returns>
    public static Color RandomColor(int alpha)
    {
        Byte[] temp = new Byte[3];
        Randomisation.NextBytes(temp);
        return new Color(temp[0], temp[1], temp[2], Mathf.Clamp(alpha, 0, 255));
    }

    /// <summary>
    /// 获取随机范围值
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static float Range(float min, float max)
    {
        return (float)Randomisation.NextDouble() * (max - min) + min;
    }

    /// <summary>
    /// 获取随机范围值
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static int Range(int min, int max)
    {
        return Randomisation.Next(min, max);
    }

    #endregion
}
